﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO;
using System.Web;
using HgCo.WindowsLive.SkyDrive;

namespace API.WindowsLive.SkyDrive.BusinessLogic
{
    partial class SkyDriveLogic
    {
        private bool webDirectoryExists(DirectoryInfo directory)
        {
            WebFolderInfo webFolder = getWebDirectory(directory);
            return (webFolder != null);
        }

        private WebFolderInfo createWebDirectory(String webDirectoryName, WebFolderInfo parentWebDirectory)
        {
            WebFolderInfo[] subDirectories = getSimpleSubDirectories(parentWebDirectory);
            foreach (WebFolderInfo webFolderInfo in subDirectories)
            {
                if (webFolderInfo.Name.ToLower().Equals(webDirectoryName.ToLower()))
                {
                    return skyDrive.GetWebFolder(webFolderInfo);
                }
            }

            if (parentWebDirectory == null)
            {
                skyDrive.CreateRootWebFolder(webDirectoryName, WebFolderItemShareType.Private);
            }
            else
            {
                skyDrive.CreateSubWebFolder(webDirectoryName, parentWebDirectory);
            }

            //Call it again to retrieve the folder
            return createWebDirectory(webDirectoryName, parentWebDirectory);
        }

        private bool localDirectoryExists(WebFolderInfo webFolder)
        {
            String localPath = HttpUtility.UrlDecode(webFolder.PathUrl).Replace(HttpUtility.UrlDecode(getWebDirectoryPath(webSyncRootDirectory)), localSyncRootDirectory.FullName);
            return Directory.Exists(localPath);
        }

        private void createLocalDirectory(WebFolderInfo webFolder)
        {
            getLocalDirectory(webFolder).Create();
        }

        private String getWebDirectoryPath(WebFolderInfo webFolder)
        {
            return (webFolder == null) ? "/" : HttpUtility.UrlDecode(webFolder.PathUrl);
        }

        /// <summary>
        /// Check if the equivilant of this file exists in the local directory, if it exists check if there if it is the latest version.
        /// </summary>
        /// <param name="webFileInfo"></param>
        /// <returns>If the file is to be downloaded or not </returns>
        private bool checkIfDownloadFile(WebFileInfo webFileInfo, Boolean ignoreSecondSplits)
        {
            FileInfo fileInfo = getLocalFile(webFileInfo);

            if (SplitLargeFiles.isSplitFile(webFileInfo.FullName) && !SplitLargeFiles.isFirstSplitFile(webFileInfo.FullName))
            {
                if (ignoreSecondSplits)
                    return true;
            }
                

            return (updateLocalFiles) ? (fileInfo.Exists && (fileInfo.LastWriteTime > webFileInfo.DateModified)) : fileInfo.Exists;
        }

        private bool checkIfUploadFile(FileInfo file)
        {
            WebFolderInfo folder = getWebDirectory(file.DirectoryName);
            return (folder == null) ? false : checkIfUploadFile(file, folder);
        }

        /// <summary>
        /// Check if the file is in the webfoder. 
        /// The check is not case sensitive, as SkyDrive does not allow 2 files with the same name with different casing.
        /// </summary>
        /// <param name="fileName">Name of the file</param>
        /// <param name="webFolder">Webfolder to look in</param>
        /// <returns>True if the file exists in the webfolder, otherwise false</returns>
        private bool checkIfFileInWebDirectory(String fileName, WebFolderInfo webFolder)
        {
            WebFileInfo[] files = skyDrive.ListSubWebFolderFiles(webFolder);

            foreach (WebFileInfo webFile in files)
                if (webFile.FullName.ToLower().Equals(fileName.ToLower()))
                    return true;

            return false;
        }

        private bool checkIfUploadFile(FileInfo file, WebFolderInfo webFolder)
        {            
            WebFileInfo[] files = skyDrive.ListSubWebFolderFiles(webFolder);

            foreach (WebFileInfo webFile in files)
            {
                if (SplitLargeFiles.isSplitFile(webFile.FullName))
                {
                    String largeFileName = SplitLargeFiles.getFileName(webFile.FullName);
                    if (largeFileName.ToLower().Equals(file.Name.ToLower()))
                    {
                        String[] partFileNames = SplitLargeFiles.getAllFileNames(webFile.FullName);
                        foreach (String partFileName in partFileNames)
                        {
                            if (!checkIfFileInWebDirectory(partFileName, webFolder))
                                return false;
                        }
                        return (updateRemoteFiles) ? (webFile.DateModified > file.LastWriteTime) : true;
                    }
                }
                else
                {
                    if (webFile.FullName.ToLower().Equals(file.Name.ToLower()))
                        return (updateRemoteFiles) ? (webFile.DateModified > file.LastWriteTime) : true;
                }
            }

            return false;
        }

        private WebFolderInfo getWebDirectoryFromRawPath(String rawPath, WebFolderInfo parentFolder)
        {
            if (rawPath.Equals(String.Empty) && parentFolder == null)
            {
                //root folder could be null if the destination is the actual rootFolder
                return webSyncRootDirectory;
            }

            String[] directoryNames = rawPath.Split(Path.DirectorySeparatorChar);
            WebFolderInfo returnWebFolder = null;
            WebFolderInfo[] webFolders;
            bool foundFolder = false;

            //webFolders = (parentFolder == null) ? skyDrive.ListRootWebFolders() : parentFolder.GetSubFolders();
            webFolders = (parentFolder == null) ? getRootDestinationSubWebDirectories() : parentFolder.GetSubFolders();
            

            foreach (String directoryName in directoryNames)
            {
                if (!directoryName.Equals(String.Empty))
                {
                    foreach (WebFolderInfo webFolder in webFolders)
                    {
                        if (webFolder.Name.ToLower().Equals(directoryName.ToLower()))
                        {
                            foundFolder = true;
                            returnWebFolder = skyDrive.GetWebFolder(webFolder);
                            webFolders = skyDrive.ListSubWebFolders(returnWebFolder);
                            break;
                        }
                    }

                    if (!foundFolder)
                        return null;
                    else
                        foundFolder = false;
                }
            }

            return returnWebFolder;
        }

        private DirectoryInfo getLocalDirectory(WebFolderInfo webFolder)
        {
            String directoryPath = HttpUtility.UrlDecode(webFolder.PathUrl).Replace(getWebDirectoryPath(webSyncRootDirectory), localSyncRootDirectory.FullName);
            return new DirectoryInfo(directoryPath);
        }

        /// <summary>
        /// Given a WebFileInfo return the parent WebFolderInfo
        /// </summary>
        /// <param name="webFile">The WebFileInfo in the web directory</param>
        /// <returns>The WebFileInfo's parent WebFolderInfo</returns>
        private WebFolderInfo getParentWebDirectory(WebFileInfo webFile)
        {
            int lastLocation = webFile.PathUrl.LastIndexOf(webDirectorySeperator);
            String fullPath = HttpUtility.UrlDecode(webFile.PathUrl.Substring(0, lastLocation));
            return getWebDirectoryFromPathURL(fullPath);
        }

        private WebFolderInfo getWebDirectory(DirectoryInfo directoryInfo)
        {
            String rawPath = directoryInfo.FullName.Replace(localSyncRootDirectory.FullName, "");
            return getWebDirectoryFromRawPath(rawPath, null); ;
        }

        /// <summary>
        /// Return web directory give local directory fullpath. Ony works with local directories.
        /// </summary>
        /// <param name="fullPath">Local directory full path.</param>
        /// <returns>The current local directory's corresponding web directory.</returns>
        private WebFolderInfo getWebDirectory(String fullPath)
        {
            String rawPath = fullPath.Replace(localSyncRootDirectory.FullName, "");
            return getWebDirectoryFromRawPath(rawPath, null);
        }


        private WebFolderInfo getWebDirectoryGivenShortWebPath(String rawPath, WebFolderInfo parentFolder)
        {
            if (rawPath.Equals(String.Empty) && parentFolder == null)
            {
                //root folder could be null if the destination is the actual rootFolder
                return webSyncRootDirectory;
            }

            String[] directoryNames = rawPath.Split(webDirectorySeperator);
            WebFolderInfo returnWebFolder = null;
            WebFolderInfo[] webFolders;
            bool foundFolder = false;

            //webFolders = (parentFolder == null) ? skyDrive.ListRootWebFolders() : parentFolder.GetSubFolders();
            webFolders = (parentFolder == null) ? getRootDestinationSubWebDirectories() : parentFolder.GetSubFolders();


            foreach (String directoryName in directoryNames)
            {
                if (!directoryName.Equals(String.Empty))
                {
                    foreach (WebFolderInfo webFolder in webFolders)
                    {
                        if (webFolder.Name.ToLower().Equals(directoryName.ToLower()))
                        {
                            foundFolder = true;
                            returnWebFolder = skyDrive.GetWebFolder(webFolder);
                            webFolders = skyDrive.ListSubWebFolders(returnWebFolder);
                            break;
                        }
                    }

                    if (!foundFolder)
                        return null;
                    else
                        foundFolder = false;
                }
            }

            return returnWebFolder;
        }

        /// <summary>
        /// return the Web directory give a web directory full path's
        /// </summary>
        /// <param name="pathURL"></param>
        /// <returns></returns>
        private WebFolderInfo getWebDirectoryFromPathURL(String pathURL)
        {
            String[] partialPaths = pathURL.Split(webDirectorySeperator);
            String newPath = "";
            for (int i = 0; i < partialPaths.Length ; i++)
            {
                if (!partialPaths[i].Equals(String.Empty))
                    newPath += "/" + partialPaths[i];
            }

            newPath = HttpUtility.UrlDecode( newPath.Replace(HttpUtility.UrlDecode(webSyncRootDirectory.PathUrl), ""));

            WebFolderInfo returnWebFolder = getWebDirectoryGivenShortWebPath(newPath, null);

            return returnWebFolder;
        }

        private FileInfo getLocalFile(WebFileInfo webFileInfo)
        {
            

            String filePath = "";
            if (SplitLargeFiles.isSplitFile(webFileInfo.FullName))
            {
                filePath = SplitLargeFiles.getFileName(HttpUtility.UrlDecode(webFileInfo.PathUrl)).Replace(getWebDirectoryPath(webSyncRootDirectory), localSyncRootDirectory.FullName);
            }
            else
            {
                filePath = HttpUtility.UrlDecode(webFileInfo.PathUrl).Replace(getWebDirectoryPath(webSyncRootDirectory), localSyncRootDirectory.FullName);
            }
            return new FileInfo(filePath);
        }

        private void createWebDirectory(DirectoryInfo directoryInfo)
        {
            WebFolderInfo parentFolder = null;

            parentFolder = (directoryInfo.FullName.ToLower().Equals(localSyncRootDirectory.FullName.ToLower())) ? parentFolder = webSyncRootDirectory : parentFolder = getWebDirectory(directoryInfo.Parent);

            skyDrive.CreateSubWebFolder(directoryInfo.Name, parentFolder);
        }

        public WebFolderInfo[] getSimpleSubDirectories(WebFolderInfo webFolder)
        {
            return (webFolder == null) ? skyDrive.ListRootWebFolders() : skyDrive.ListSubWebFolders(webFolder);  //webFolder.GetSubFolders();
        }

        public WebFolderInfo[] getSubDirectories(WebFolderInfo webFolder)
        {
            return (webFolder == null) ? getRootDestinationSubWebDirectories() : skyDrive.ListSubWebFolders(webFolder);  //webFolder.GetSubFolders();
        }

        public WebFolderInfo[] getRootDestinationSubWebDirectories()
        {
            return (webSyncRootDirectory == null) ? skyDrive.ListRootWebFolders() : skyDrive.ListSubWebFolders(webSyncRootDirectory);
        }

        public WebFileInfo getWebFile(String fileName, WebFolderInfo webFolderInfo)
        {
            foreach (WebFileInfo webFileInteration in skyDrive.ListSubWebFolderFiles(webFolderInfo))
            {
                if (webFileInteration.FullName.ToLower().Equals(fileName.ToLower()))
                {
                    return webFileInteration;
                }
            }

            return null;
        }

        public WebFileInfo[] getWebFiles(WebFolderInfo webFolder)
        {
            return (webFolder == null) ? getRootDestinationWebFiles() : skyDrive.ListSubWebFolderFiles(webFolder);  //webFolder.GetFiles();
        }

        public WebFileInfo[] getRootDestinationWebFiles()
        {
            return (webSyncRootDirectory == null) ? (WebFileInfo[])skyDrive.ListRootWebFolderItems() : skyDrive.ListSubWebFolderFiles(webSyncRootDirectory);
        }

        public WebFolderInfo checkAndCreateWebFolders(String DirectoryName)
        {
            String[] directories = DirectoryName.Split('\\');
            //String currentDirectoryName = webDirectorySeperator;
            WebFolderInfo currentDirectory = null;

            foreach (String directoryName in directories)
            {
                if (!directoryName.Equals(String.Empty))
                    currentDirectory = createWebDirectory(directoryName, currentDirectory);
            }

            return currentDirectory;
        }

    }
}
